/*******************************************************************************
 * Copyright (c) 2015 Lincong All rights reserved.
 * This software is the confidential and proprietary information of Lincong.
 * You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Lincong.
 *  Mail: Lincong <lincong1987@gmail.com>, <lincong@cleverlin.com>
 *    QQ: 159257119
 * Phone: 15925711961
 * $Revision$
 * $Id$
 ******************************************************************************/


define(function (require, exports, module) {

	require("Firebird.lang.HashMap");
	require("Firebird.ui.Component");
	require("Firebird.ajax.Post");

	Firebird.define("Firebird.ui.CheckGroup", {
		extend: "Firebird.ui.Component",
		statics: {
			_uuid: 1,
			uuid: function () {
				return this._uuid++;
			},
			zIndex: 100,
			/**
			 * 属性适配器
			 * @param $component
			 * @returns {{}}
			 */
			attrs: function ($component) {

				$component.hide(0);

				return $.extend(true, {}, {

					renderTo: $component.get(0),

					// 实例ID, 可以在 context 里直接获取， var ins = context.getInstance("name");
					instanceId: $component.attr("fb-instance") || $component.attr("name") || $component.attr("id") || ("checkgroup_" + Firebird.ui.CheckGroup.uuid()),

					// h is horizontal 横向, v is vertical 垂直
					align: $component.attr("fb-align") || "h",
					type: ($component.attr("fb-type") || "checkbox") == "checkbox" ? "checkbox" : "radio",
					name: $component.attr("fb-name") || $component.attr("name"),

					// 数据源，优先级为 cache > data > url
					cache: $component.attr("fb-cache"),
					url: $component.attr("fb-url"),
					data: Firebird.ui.Component.eval($component.attr("fb-data")),
					param: Firebird.ui.Component.eval($component.attr("fb-param")) || {},

					reader: $.extend(true, {}, {
						text: "name",
						id: "id",
						title: "title",
						checked: "checked"
					}, Firebird.ui.Component.eval($component.attr("fb-reader")) || {}),

					valueSeparator: $component.attr("fb-value-separator") || ",",
					textSeparator: $component.attr("fb-text-separator") || ",",

					disabled: Firebird.ui.Component.eval($component.attr("fb-disabled") || $component.prop("disabled")) || false,
					readonly: Firebird.ui.Component.eval($component.attr("fb-readonly") || $component.prop("readonly")) || false,
					hidden: Firebird.ui.Component.eval($component.attr("fb-hidden") || $component.is("[type=hidden]")) || false
				});
			}
		},

		config: {
			renderTo: null,
			instanceId: null,

			align: null,
			type: null,
			name: null,

			cache: null,
			url: null,
			data: null,
			param: null,

			reader: null,

			valueSeparator: null,
			textSeparator: null,

			disabled: null,
			focus: null,
			readonly: null,
			hidden: null
		},

		// 属性定义
		defaults: function (options) {
			return {};
		},

		checkTimer: 0,

		triggerTimer: 0,

		wrapCls: "fb-ui-checkgroup",

		_remoteSuccess: false,

		_init: function () {
			var me = this;
			me.tmpl = require("../tmpl/checkgroup.tmpl");
			var genId = me.genId = Firebird.Model.getGenId();
			me.instance = $(me.getRenderTo()).css({
				display: "none"
			}).data({
				instance: me,
				xtype: "checkgroup"
			});

			this.nodesMap = Firebird.create(Firebird.lang.HashMap);


			this.render();

			this.genData();

			this.setReadonly(this.getReadonly() || false);
			this.setDisabled(this.getDisabled() || false);
			this.setHidden(this.getHidden() || false);

		},


		proxy: function (func) {
			if (!this[func]) {
				return function () {
				};
			} else {
				this.instance.trigger(func);
				return this[func];
			}
		},

		onAjaxLoadSuccess: function (data) {

		},

		getAsyncData: function (callback) {
			callback && callback();
		},

		onLoad: function () {

		},


		/**
		 * 处理渲染控件
		 */
		render: function () {

			var me = this;
			var tpl = me.tmpl({
				_type: "wrapper",
				genId: me.genId,
				wrapCls: me.wrapCls,
				vorh: me.getAlign() == "v" ? "vertical" : "horizontal"
			});

			me.instance.before(tpl);
			me.wrapper = Firebird.get(me.genId + "-wrapper").data("instance", me);

			me.wrapper.data("instance", me);
			me.wrapper.append(me.instance);

			this.wrapper.on("mouseenter", function () {
				me.wrapper.addClass(me.wrapCls + "-hover");
				if (me.wrapper.hasClass(me.wrapCls + "-invalid")) {
					me.instance.trigger("showErrorMessage");
					//me.wrapper.removeClass(me.wrapCls + "-invalid");
				}
			});

			this.wrapper.on("mouseleave", function () {
				me.wrapper.removeClass(me.wrapCls + "-hover");
				if (me.wrapper.hasClass(me.wrapCls + "-invalid")) {
					me.instance.trigger("hideErrorMessage");
					//me.wrapper.removeClass(me.wrapCls + "-invalid");
				}
			});

		},

		/**
		 * 加载数据
		 * 提供3种数据加载方式
		 * 1、firebird 全局缓存
		 * 2、静态数据
		 * 3、ajax加载
		 */
		genData: function () {
			var me = this;
			if (this.getCache()) {
				me.addRoot(me.dataFilter(firebird.data.get(this.getCache())));
			} else if (this.getData()) {
				me.addRoot(me.dataFilter(this.getData()));
			} else if (this.getUrl()) {
				this.loader = Firebird.create("Firebird.ajax.Post", {
					url: this.getUrl().replace(/\{contextPath\}\//, firebird.api.get("contextPath")),
					error: function () {
						me.addRoot([]);
					},
					success: function (json) {
						me.addRoot(me.dataFilter(json.data));
					}
				});
			} else {
				me.addRoot([]);
			}
		},

		/**
		 * 添加数据
		 * @param data
		 */
		addRoot: function (data) {
			this._remoteSuccess = true;
			this.addNodes(data);
			this.setValue(this.instance.attr("fb-value") || this.instance.val());
			this.onLoad.apply(this, [data]);
		},


		addNodes: function (nodes, callback) {
			var me = this;
			$.each(nodes || [], function (i, node) {
				me.addNode(node, callback);
			});
			return me;
		},


		addNode: function (_node, callback) {
			var me = this,
				reader = me.getReader(),
				id = _node[reader.id],
				text = _node[reader.text],
				checked = _node[reader.checked],
				title = _node[reader.title] || text;

			var tpl = me.tmpl({
				_type: "node",
				id: id,
				text: text,
				title: title,
				name: me.getName(),
				genId: me.genId,
				wrapCls: me.wrapCls,
				type: me.getType(),
				node: _node,
				checked: checked
			});

			me.wrapper.append(tpl);

			var node = {
				$label: Firebird.get(me.genId + "-" + id + "-label"),
				$checkbox: Firebird.get(me.genId + "-" + id + "-input"),
				$text: Firebird.get(me.genId + "-" + id + "-text"),
				checkNode: function (checked) {
					checked = !!checked;
					this.$checkbox.prop("checked", checked);
					me.proxy("onCheck").apply(this, [this, checked]);
					return this;
				},
				isChecked: function () {
					return this.$checkbox.prop("checked");
				},
				prop: function (attr, status) {
					if (attr === "checked") {
						return this.checkNode(status);
					} else {
						return this.$checkbox.prop.apply(this.$checkbox, $.makeArray(arguments));
					}
				},
				setText: function (text) {
					this.text = text;
					this.$text.html(text);
				},
				id: id,
				text: text
			};

			me.nodesMap.put(id, node);

			node.$checkbox
				.on("click", function (e) {
					me.proxy("onClick").apply(this, [e, node, $(this).prop("checked")]);
					me.setValue(me.getValue());


				})
				.on("change", function (e) {
					me.proxy("onChange").apply(this, [e, node, $(this).prop("checked")]);
					me.setValue(me.getValue());

					// me.instance.trigger("validation");
					// debugger
				});

			me.proxy("onAdd").apply(this, [node]);
		},

		dataFilter: function (data) {
			return data;
		},

		on: function () {
			this.instance.on.apply(this.instance, arguments);
		},

		applyHidden: function (status) {
			if (this.instance) {
				this.wrapper[!!status ? "hide" : "show"](0);
			}
			return status;
		},

		applyDisabled: function (status) {
			if (this.instance) {
				status = !!status;
				this.wrapper[status ? "addClass" : "removeClass"](this.wrapCls + "-disabled");
				this.nodesMap.each(function (id, node) {
					node.$checkbox.prop("disabled", status);
				});
			}
			return status;
		},

		applyReadonly: function (status) {
			if (this.instance) {
				status = !!status;
				this.wrapper[status ? "addClass" : "removeClass"](this.wrapCls + "-readonly");
				this.nodesMap.each(function (id, node) {
					node.$checkbox.prop("readonly", status);
				});
			}
			return status;
		},

		/**
		 * beforeShow
		 */
		beforeShow: function () {
		},
		/**
		 * onSuccess
		 */
		onSuccess: function () {
		},
		/**
		 * onError
		 */
		onError: function () {
		},
		/**
		 * onComplete
		 */
		onComplete: function () {
		},
		/**
		 * beforeClick
		 */
		beforeClick: function () {
		},
		/**
		 * onClick
		 */
		onClick: function () {
		},
		/**
		 * onCheck
		 */
		onCheck: function () {
		},
		/**
		 * onChange
		 */
		onChange: function () {
		},
		/**
		 * getValue
		 * @returns {string}
		 */
		getValue: function () {
			return this._getValue();
		},

		/**
		 * getCheckedNodes
		 * @see Firebird.ui.MultiSelecter#_getCheckedNodes
		 * @param {Boolean} checked
		 * @returns {Array|null}
		 */
		getCheckedNodes: function (checked) {
			return this._getCheckedNodes(checked || true);
		},

		checkNodes: function (nodes, checked) {
			var me = this;
			$.each(nodes, function (i, node) {
				me.checkNode(node, checked);
			});
			return this;
		},

		checkNode: function (node, checked) {
			if (node) {
				node.$checkbox.prop("checked", checked);
				this.instance.proxy("onNodeRemove").apply(this, [node]);
			}
			return this;
		},

		checkNodesByIds: function (ids, checked) {
			var me = this, reader = me.getReader();
			$.each(ids, function (i, node) {
				me.checkNodeById(node[reader.id], checked);
			});
			return this;
		},

		/**
		 * 勾选目标元素
		 * @param id
		 * @param checked
		 * @returns {Firebird.ui.CheckGroup}
		 */
		checkNodeById: function (id, checked) {
			var node = this.nodesMap.get(id);
			if (node) {
				node.$checkbox.prop("checked", checked);
			}
			return this;
		},

		getNodeById: function (id) {
			return this.nodesMap.get(id);
		},


		/**
		 * setValue
		 * @param value
		 */
		setValue: function (value) {
			this._setValue(value);
		},
		/**
		 * _getValue
		 * @returns {string}
		 * @private
		 */
		_getValue: function () {
			var ids = [];
			this.nodesMap.each(function (id, node) {
				if (node.$checkbox.prop("checked") === true) {
					ids.push(node.id);
				}
			});

			return ids.join(this.getValueSeparator());
		},

		/**
		 * 字符串转数组
		 * @param value
		 * @returns {*}
		 */
		str2array: function (value) {
			var me = this, valueSeparator = me.getValueSeparator();

			if (!value || $.trim(value) === "") {
				return [];
			}

			return value.toString().split(valueSeparator);
		},

		/**
		 * _setValue
		 * @param value
		 * @private
		 */
		_setValue: function (value) {
			var me = this;

			me.nodesMap.each(function (id) {
				me.checkNodeById(id, false);
			});

			var ids = me.str2array(value);

			if (me.getType() === "radio" && ids.length > 1) {
				ids = [ids[0]];
			}

			$.each(ids, function (i, id) {
				me.checkNodeById(id, true);
			});

			if (this.instance) {
				this.instance.val(me.getValue());
				this.instance.trigger("focusout");
			}
		},
		getText: function () {
			return this._getText();
		},
		/**
		 * _getText
		 * @returns {string}
		 * @private
		 */
		_getText: function () {
			var texts = [];
			this.nodesMap.each(function (id, node) {
				if (node.$checkbox.prop("checked") === true) {
					texts.push(node.text);
				}
			});

			return texts.join(this.getTextSeparator());
		},
		/**
		 * _getCheckedNodes
		 * @param checked
		 * @returns {Array|null}
		 * @private
		 */
		_getCheckedNodes: function (checked) {
			checked = !!checked;

			var nodes = [];
			this.nodesMap.each(function (id, node) {
				if (node.isChecked() == true) {
					nodes.push(node);
				}
			});

			return nodes;
		},

		/**
		 * 移除节点
		 */
		removeNodesByIds: function (ids) {
			var me = this;
			$.each(ids || [], function (i, id) {
				me.removeNodeById(id);
			});
			return me;
		},

		removeNodeById: function (id) {
			var node = this.getNodeById(id);
			if (node) {
				this.proxy("onRemove").apply(this, [node]);
				node.$label.remove();
				this.nodesMap.remove(id);
				this.setValue(this.getValue());
			}
			return this;
		},

		/**
		 * 获得所有节点
		 *
		 * @returns {*}
		 */
		getAllNodes: function () {
			return this.nodesMap.values();
		},

		clearCheckedNodes: function () {
			this.setValue("");
			return this;
		},

		clear: function () {
			return this.clearCheckedNodes();
		}
	});

	module.exports = Firebird.ui.CheckGroup;

});